﻿#define _CRT_SECURE_NO_WARNINGS 1

#include"Snake.h"

void TurnConsoleInfo()
{
	//更改控制台大小
	system("mode con cols=120 lines=30");
	//更改控制台名字
	system("title 贪吃的小涵");
	//获取句柄
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	//创建一个控制台光标的结构体变量，用来存储光标信息;
	CONSOLE_CURSOR_INFO consolecursorinfo;
	GetConsoleCursorInfo(houtput, &consolecursorinfo);
	consolecursorinfo.bVisible = false;
	//根据该结构体的信息，对控制台光标进行设置;
	SetConsoleCursorInfo(houtput, &consolecursorinfo);	
}
//封装一个修改光标位置的函数；
void SetPos(int x, int y)
{
	COORD pos = { x,y };
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(houtput, pos);
}
void WelcomePlayer()
{
	//界面1
	SetPos(35, 10);
	printf("欢  迎  来  到  贪  吃  蛇  小  游  戏");
	SetPos(35, 14);
	printf("@出版者：碎残风  @发行者：庄梦涵");
	SetPos(40, 20);
	system("pause");
	//界面2
	system("cls");
	double x, y, a;int i = 0;
	for (y = 1.5; y > -1; y -= 0.1)
	{
		system("color 0c");
		for (x = -1.5; x < 1.5; x += 0.05)
		{
			a = x * x + y * y - 1;
			putchar(a * a * a - x * x * y * y * y < 0.0 ? '*' : ' ');
		}
		Sleep(10);
		printf("\n");
	}
	SetPos(60, 3);
	printf("小宝，你还知道回来呀！！！");
	SetPos(60, 5);
	printf("\t风铃响，故人归，我在等风起，也在等你归！！！");	
	SetPos(60, 7);
	printf("  /\\_/\\");
	SetPos(60, 8);
	printf(" ( o.o )");
	SetPos(60, 9);
	printf("  > ^ <");
	SetPos(70, 9);
	printf("游戏正在加载中......");
	//界面3
	Sleep(2000);
	system("cls");
	SetPos(30, 10);
	printf("玩家可通过.↑.↓.←.→.F4加速.F3减速，来操作：名为小涵的贪吃蛇");
	SetPos(30, 12);
	printf("温馨提示：加速将会得到更高的分数！！！");
	SetPos(45, 20);
	Sleep(1800);
	system("cls");
}
void CreatMap()
{
	SetPos(0, 0);
	for (int i = 0; i < 56; i += 2)
	{
		wprintf(L"%lc", WCHAR);
	}
	SetPos(0, 27);
	for (int i = 0; i < 56; i += 2)
	{
		wprintf(L"%lc", WCHAR);
	}
	for (int i = 1; i < 28; i += 1)
	{
		SetPos(0, i);
		wprintf(L"%lc", WCHAR);
	}
	for (int i = 1; i < 28; i += 1)
	{
		SetPos(54, i);
		wprintf(L"%lc", WCHAR);
	}
}
pSNAKE SnakeInit()
{
	//创建空间
	pSNAKE snake = (pSNAKE)calloc(1, sizeof(SNAKE));
	if (snake == NULL)
		return;
	//生成五个蛇结点
	for (int i = 0; i < 5; i++)
	{
		pSnakeNode nextnode = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (nextnode != NULL)
		{
			nextnode->x = INITPOSX + i * 2;
			nextnode->y = INITPOSY;
			nextnode->next = NULL;
			if (snake->_snake == NULL)
			{
				snake->_snake = nextnode;
			}
			else
			{
				nextnode->next = snake->_snake;
				snake->_snake = nextnode;
			}
		}
	}
	//打印
	pSnakeNode cur = snake->_snake;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", SNODE);
		cur = cur->next;
	}
	free(cur);
	cur = NULL;
	//其余成员的初始化
	snake->_food = NULL;
	snake->_direct = RIGHT;
	snake->_state = OK;
	snake->foodweight = 10;
	snake->sleepweight = 200;
	//返回
	return snake;
}
void GetFoodNode(pSNAKE snake)
{
	int x = 0, y = 0;
again:
	do
	{
		x = rand() % 51 + 2;//2~52
		y = rand() % 26 + 1;//1~26
	} while (x % 2 != 0);
	pSnakeNode cur = snake->_snake;
	while (cur)
	{
		if (cur->x == x && cur->y == y)
			goto again;
		cur = cur->next;
	}
	SetPos(x,y);
	wprintf(L"%lc", FNODE);
	//保存食物信息
	snake->_food = (pSnakeNode)malloc(sizeof(SnakeNode));
	snake->_food->x = x;
	snake->_food->y = y;
}
void HelpExplat(pSNAKE snake)
{
	SetPos(65, 7);
	int MAXSCORE = 0;
	printf("本局游戏得分%3d   历史最高的分%3d", snake->score, MAXSCORE);
	SetPos(65, 8);
	printf("当前游戏速度%3d   单个食物得分%3d", snake->sleepweight, snake->foodweight);
	SetPos(65, 15);
	printf("玩家可通过.↑.↓.←.→.F3.F4来控制小涵");
	SetPos(65, 16);
	printf(".↑.↓.←.→.用来控制方向");
	SetPos(65, 17);
	printf(".F3用来减速.F4用来加速.");
	SetPos(65, 18);
	printf("若撞到墙体或自身则判定为游戏结束");
	SetPos(65, 19);
	printf("@版权归庄梦涵所有");
	SetPos(65, 23);
	printf("-----------------------------------");
	SetPos(65, 27);
	printf("-----------------------------------");
	SetPos(66, 25);
	printf("当前游戏状态：  ");
	system("pause");
}
static void Pause()
{
	while (1)
	{
		SetPos(65, 23);
		printf("-----------------------------------");
		SetPos(65, 27);
		printf("-----------------------------------");
		SetPos(66, 25);
		printf("当前游戏状态：        暂停中          ");
		Sleep(100);
		if (KEY_PRESS(VK_SPACE))
			break;			
	}
}
void TurnSnakeDirection(pSNAKE snake)
{
	if ((KEY_PRESS(VK_UP) == 1) && (snake->_direct != DOWN))
	{
		snake->_direct = UP;
	}
	else if ((KEY_PRESS(VK_DOWN) == 1) && (snake->_direct != UP))
	{
		snake->_direct = DOWN;
	}
	else if ((KEY_PRESS(VK_LEFT) == 1) && (snake->_direct != RIGHT))
	{
		snake->_direct = LEFT;
	}
	else if ((KEY_PRESS(VK_RIGHT) == 1) && (snake->_direct != LEFT))
	{
		snake->_direct = RIGHT;
	}
	else if (KEY_PRESS(VK_SPACE) == 1)
	{
		Pause();
	}
	else if (KEY_PRESS(VK_ESCAPE) == 1)
	{
		snake->_state = END_GAME;
	}
	else if (KEY_PRESS(VK_F3) == 1)
	{
		if (snake->sleepweight < 320)
		{
			snake->sleepweight += 20;
			if (snake->foodweight > 4)
				snake->foodweight -= 2;
		}
	}
	else if (KEY_PRESS(VK_F4) == 1)
	{
		if (snake->sleepweight > 150)
		{
			snake->sleepweight -= 10;
			if (snake->foodweight < 20)
				snake->foodweight += 2;
		}
	}
}
pSnakeNode GetSnakeNode(pSNAKE snake)
{
	pSnakeNode next = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (next == NULL)
		return;
	switch (snake->_direct)
	{
	case UP:
		next->x = snake->_snake->x;
		next->y = snake->_snake->y - 1;
		break;
	case DOWN:
		next->x = snake->_snake->x;
		next->y = snake->_snake->y + 1;
		break;
	case LEFT:
		next->x = snake->_snake->x - 2;
		next->y = snake->_snake->y;
		break;
	case RIGHT:
		next->x = snake->_snake->x + 2;
		next->y = snake->_snake->y;
		break;
	}
	next->next = NULL;
	return next;
}
void JudgeGameState(pSNAKE snake, pSnakeNode nextnode)
{
	//判断是否撞墙;
	if (nextnode->x == 0 || 
		nextnode->x == 54|| 
		nextnode->y == 0 || 
		nextnode->y == 27)
	{
		snake->_state = KILL_WALL;
	}
	//判断是否自杀；
	pSnakeNode cur = snake->_snake;
	while (cur)
	{
		if (nextnode->x == cur->x && nextnode->y == cur->y)
		{
			snake->_state = KILL_SELF;
			break;
		}
		cur = cur->next;
	}
}
bool JudgeFood(pSNAKE snake, pSnakeNode food)
{
	bool ret = ((food->x == snake->_food->x && food->y == snake->_food->y) ? true : false);
	return ret;
}
void EATFOOD(pSNAKE snake, pSnakeNode food)
{
	//头插
	food->next = snake->_snake;
	snake->_snake = food;
	//打印头部
	SetPos(snake->_snake->x, snake->_snake->y);
	wprintf(L"%lc", SNODE);
	//加分；
	snake->score += snake->foodweight;
	//生成新食物
	GetFoodNode(snake);
}
void NOFOOD(pSNAKE snake, pSnakeNode food)
{
	//头插
	food->next = snake->_snake;
	snake->_snake = food;
	//尾删
	pSnakeNode prev = NULL;
	pSnakeNode cur = snake->_snake;
	while (cur->next != NULL)
	{
		prev = cur;
		cur = cur->next;
	}
	//尾部打印成空白
	SetPos(cur->x, cur->y);
	printf("  ");
	//free空间
	free(cur);
	prev->next = NULL;
	//打印头部
	SetPos(snake->_snake->x, snake->_snake->y);
	wprintf(L"%lc", SNODE);
}